use rp235x_hal::pio::PIO;

const I2S_OUT_WRAP_TARGET: u32 = 0;
const I2S_OUT_WRAP: u32 = 7;
const I2S_OUT_PIO_VERSION: u32 = 1;
const I2S_OUT_OFFSET_ENTRY_POINT: u32 = 0;

const I2S_OUT_PROGRAM_INSTRUCTIONS: [u16; 8] = [
    //     .wrap_target
    0x8080, //  0: pull   noblock         side 0
    0xe83e, //  1: set    x, 30           side 1
    0x6001, //  2: out    pins, 1         side 0
    0x0842, //  3: jmp    x--, 2          side 1
    0x9080, //  4: pull   noblock         side 2
    0xf83e, //  5: set    x, 30           side 3
    0x7001, //  6: out    pins, 1         side 2
    0x1846, //  7: jmp    x--, 6          side 3
            //     .wrap
];

const I2S_PIO_INSTRUCTIONS_PER_BIT: u32 = 2;
const I2S_NUM_CHANNELS: u32 = 2;

/**
 * @brief Configuration for a PioI2S instance.
 *
 */
pub struct PioI2SConfig {
    /**
     * @brief The data pin.
     */
    data_pin: i32,

    /**
     * @brief The bit clock pin.
     */
    bclk_pin: i32,

    /**
     * @brief The bit depth to use.
     * This must match the bit depth supported by your I2S device.
     * Note currently only 32 bit samples are supported.
     */
    bit_depth: int,

    /**
     * @brief The sample rate in Hz.
     * This must match a sample rate supported by your I2S device.
     */
    sample_rate: int32_t,

    /**
     * @brief The audio sample block size to use.
     */
    block_size: int,

    /**
     * @brief The PIO instance to use.
     */
    pio: PIO,
}

/**
 * @brief The PioI2S object.
 *
 */
pub struct PioI2S {
    /**
     * @brief A pointer to the configuration for this PioI2S instance.
     */
    config: PioI2SConfig,

    /**
     * @brief The PIO state machine index.
     */
    sm: i32,

    /**
     * @brief The index of the data DMA channel.
     */
    data_channel: i32,

    /**
     * @brief The index of the control DMA channel.
     */
    control_channel_l: i32,

    /**
     * @brief The size of a stereo audio block.
     */
    stereo_block_size: usize,

    /**
     * @brief The size of internal double output buffer.
     */
    double_buffer_size: usize,

    /**
     * @brief The output buffer, which must be twice the size of a stereo block.The client is responsible for allocating this buffer.
     */
    output_double_buffer: *mut i32,

    /**
     * @brief An array storing addresses to the two output buffers.
     */

    #[repr(align(8))]
    buffer_pointers: [*mut i32; 2],
    // __attribute__((aligned(8))) int32_t* bufferPointers[2],
    /**
     * @brief The index of the current output buffer.
     */
    buffer_pointer_idx: i32,

    /**
     * @brief A pointer to the DMA interrupt handler function.
     */
    // void(*dmaHandler)(void);
    dma_handler: fn(),
}

impl PioI2S {
    pub fn new(config: PioI2SConfig, output_double_buffer: i32, dma_handler: fn()) -> Self {}

    pub fn init_pio_program(&self) {}

    pub fn init_control_channel(&self) {}

    pub fn init_data_channel(&self) {}

    pub fn init_dmairq(&self) {}

    pub fn init_dma(&self) {}

    pub fn start(&self) {}

    pub fn next_output_buffer(&self) {}

    pub fn end_dma_interrupt_handler(&self) {}

    pub fn out_program_get_default_config(offset: int) {}

    pub fn calc_clock_division(&self) -> f32 {}

    pub fn verify_pioclock_division(&self, frequency_ratio: f32) {}
}

/**
 * @brief Converts a float sample in the range of 1.0 to -1.0 to a 32-bit
 * signed integer.
 *
 * @param sample the sample to convert
 * @return int32_t the converted sample
 */
pub fn float_to_int32(sample: f32) {}

/**
 * @brief Writes a stereo pair of samples to an interleaved output buffer.
 *
 *  @param left the left channel sample
 * @param right the right channel sample
 * @param interleavedOutput the output buffer to write into
 * @param i the audio frame index
 */
pub fn write_samples() {}

/**
 * @brief Writes a pair of stereo audio blocks to the interleaved output buffer.
 *
 * @param left the left channel samples
 * @param right the right channel samples
 * @param blockSize the block size
 * @param interleavedOutput the output buffer to write into
 */
pub fn write_stereo(left: i32, right: i32, block_size: usize, mut interleaved_output: i32) {}
// void PioI2s_(float* left, float* right,
//     size_t blockSize, int32_t* interleavedOutput);

/**
 * @brief Writes a mono audio block to the interleaved output buffer.
 *
 * @param mono the sample block to write
 * @param blockSize the block size
 * @param interleavedOutput the output buffer to write into
 */
pub fn write_mono(mono: i32, block_size: usize, mut interleaved_output: i32) {}
// void PioI2s_writeMono(float* mono, size_t blockSize,
//     int32_t* interleavedOutput);
